package com.dragon.www.haier.model.xml;

import android.util.Log;

import com.dragon.www.haier.adapter.ICommonArrayAdapter;
import com.dragon.www.haier.model.ActionPacket;
import com.dragon.www.haier.model.DevicePacket;
import com.dragon.www.haier.net.AppSocket;
import com.dragon.www.haier.net.AppUDPPacket;
import com.dragon.www.haier.net.Utils;
import com.dragon.www.haier.service.DevicePacketFactory;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetSocketAddress;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * 数据字典编码模板
 * Created by Administrator on 2015/11/19 18:40.
 * Author: songxy
 * Email: thinkdata@163.com
 */
public class CodeTemplate extends ATemplate {

	private static final String TAG = "com.hem.app.znjj.model.xml.CodeTemplate";

	CodeTemplate() {}

	/**
	 * 获取CODE模板类型
	 * @return
	 */
	public String[] getCodeTemplateGroupName() {
		List<String> result;
		if (this.codeTemplate.size()>0) {
			result = new ArrayList<>();
			for (DictionaryGroupItem temp : this.codeTemplate.keySet()) {
				result.add(temp.getGroupName());
			}
			return result.toArray(new String[this.codeTemplate.keySet().size()]);
		}
		return null;
	}

	/**
	 *	从数据字典编码模板中解析包
	 * @param obj 指令对象
	 * @param packetType 指令类型
	 * @param actionArgs 操作参数
	 * @return
	 */
	public AppUDPPacket encodePacket(ICommonArrayAdapter obj, String packetType, String... actionArgs) throws CodeParseException {
		byte[] groupId = checkPacketCodeTemplate(obj.getTemplateName(), packetType, actionArgs);
		AppUDPPacket packet = new ActionPacket();
		int groupLength = getGroupActionLengthCodeTemplate(obj.getTemplateName());
		Iterator<DictionaryItem> itemIterator = this.requestTemplate.get(packetType).iterator();
		while (itemIterator.hasNext()) {
			DictionaryItem item = itemIterator.next();
			// 类型
			if (item.getName().equals("type")) {
				packet.setAction(item.getActionValue());
				//数据类型
			} else if (item.getName().equals("dataFormat")) {
				//默认8个字节
				ByteBuffer actionData = ByteBuffer.allocate(8);
				Iterator<DictionaryItemField> fieldIterator = item.fields.iterator();
				while (fieldIterator.hasNext()) {
					DictionaryItemField field = fieldIterator.next();
					if (field.getName().equals("GROUPID")) {
						actionData.put(groupId);
					} else if (field.getName().equals("ID")) {
						//窗帘和空调跳过id
						if (obj.getTemplateName().equals("curtain_device") ||
								obj.getTemplateName().equals("air_container")) {
							continue;
						}
						actionData.put(Utils.long2LHByte(obj.getDeviceId(), field.getActionLength()));
					} else if (field.getName().contains("ACTION_PARAM")) {
						for (String args : actionArgs) {
							actionData.put(getCodeActionArgs(obj.getTemplateName(), args));
						}
					}
				}
				actionData.rewind();
				actionData.order(ByteOrder.LITTLE_ENDIAN);

				packet.setPacketData(actionData.array());
				//长度临时不用
				packet.setPacketDataLength((short) -1);
			}
		}
		return packet;
	}

	//由于协议没有区分包头、包体，需要获取裸包，并按照action处理
	public DevicePacket decodePacket(AppUDPPacket devicePacket, AppSocket appSocket) throws CodeParseException {
		try {
			//默认的最长大小300，所有设备状态
			DatagramPacket rawPacket = appSocket.receiveRawMsgFromNetwork(devicePacket);
			ByteBuffer temp = devicePacket.readPacketHeader(rawPacket);
			if (temp == null) return null;
			byte[] type = devicePacket.getAction();
			Log.e(TAG, " Receive Data from Remote: "
					+ ((InetSocketAddress) rawPacket.getSocketAddress()).getHostName()
					+ " Action: " + Utils.byte2HexString(type));
			if (Arrays.equals(type, DevicePacketFactory.KEY_ACTION_DATAGRAM_TYPE_LOGIN)) {
				devicePacket.setPacketDataLength((short) 1);
			} else if (Arrays.equals(type, DevicePacketFactory.KEY_ACTION_DATAGRAM_TYPE_QUIT)) {
				devicePacket.setPacketDataLength((short) 1);
			} else if (Arrays.equals(type, DevicePacketFactory.KEY_ACTION_DATAGRAM_TYPE_DETECT)) {
				devicePacket.setPacketDataLength((short) 1);
			} else if (Arrays.equals(type, DevicePacketFactory.KEY_ACTION_DATAGRAM_TYPE_ACTION)) {
				devicePacket.setPacketDataLength((short) 8);
			} else if (Arrays.equals(type, DevicePacketFactory.KEY_ACTION_DATAGRAM_TYPE_ACTION_DETECT_1)) {
				devicePacket.setPacketDataLength((short) (32*8));
			} else if (Arrays.equals(type, DevicePacketFactory.KEY_ACTION_DATAGRAM_TYPE_ACTION_DETECT_2)) {
				return null;
			} else {
				Log.e(TAG, "UDPSocketHandlerRunnable Unsupported Action Type " + type);
			}
			devicePacket.readPacketObject(temp);
			devicePacket.readPacketTail(temp);
			return (DevicePacket) devicePacket;
		}catch (IOException e) {
			throw new CodeParseException("Code Template Parse "+e.getMessage(), e);
		}catch (BufferUnderflowException e) {
			throw new CodeParseException("Code Template Parse "+e.getMessage(), e);
		}
	}

	public String[] decodePacket(String groupName, String... actionArgs) throws CodeParseException {
		String[] result = new String[actionArgs.length];
		Iterator<DictionaryItem> itemIterator = this.codeTemplate.get(groupName).iterator();
		while (itemIterator.hasNext()) {

		}
		return result;
	}

	public List<DictionaryItem> getCodeTemplateItems(String groupName) {
		for (Map.Entry<DictionaryGroupItem, List<DictionaryItem>> temp
				: this.codeTemplate.entrySet()) {
			if (temp.getKey().getGroupName().equals(groupName))
				return (temp.getValue());
		}
		return null;
	}

	public boolean addField(String fieldName) {
		return true;
	}

	public boolean delField(String fieldName) {
		return false;
	}

	public void saveAllFields() {

	}

	private boolean hasCodeTemplate(String groupName) {
		for (DictionaryGroupItem groupItem : this.codeTemplate.keySet()) {
			if (groupItem.getGroupName().equals(groupName)) return true;
		}
		return false;
	}

	private byte[] getGroupIdCodeTemplate(String groupName) {
		for (DictionaryGroupItem groupItem : this.codeTemplate.keySet()) {
			if (groupItem.getGroupName().equals(groupName))
				return groupItem.getGroupActionValue();
		}
		return null;
	}

	private int getGroupActionLengthCodeTemplate(String groupName) {
		for (DictionaryGroupItem groupItem : this.codeTemplate.keySet()) {
			if (groupItem.getGroupName().equals(groupName)) return groupItem.getGroupActionLength();
		}
		return 0;
	}

	/**
	 * 操作的组名和参数ITEM值
	 * 两者都不为null
	 * @param groupName
	 * @param actionArgs
	 * @return
	 */
	private boolean hasCodeActionArgs(String groupName, String... actionArgs) {
		boolean result = false;int i=0;
		for (DictionaryGroupItem groupItem : this.codeTemplate.keySet()) {
			if (groupItem.getGroupName().equals(groupName)) {
				List<String> args = Arrays.asList(actionArgs);
				for (DictionaryItem item : groupItem.items) {
					if (args.contains(item.getName()) && item.getActionValue() != null) {
						result = true;
						i++;
					}
				}
			}
		}
		return result && (i == actionArgs.length);
	}

	private byte[] getCodeActionArgs(String groupName, String actionArg) {
		for (DictionaryGroupItem groupItem : this.codeTemplate.keySet()) {
			if (groupItem.getGroupName().equals(groupName)) {
				for (DictionaryItem item : groupItem.items) {
					if (actionArg.equals(item.getName())) {
						return item.getActionValue();
					}
				}
			}
		}
		return null;
	}

	private byte[] checkPacketCodeTemplate(String groupName, String packetType, String... actionArgs) {
		if (!this.requestTemplate.containsKey(packetType.toLowerCase())) {
			throw new CodeException("No " + packetType + " type in requestTemplate");
		}
		byte[] groupId = getGroupIdCodeTemplate(groupName);
		if (groupId == null) {
			throw new CodeException("Group Name's "+groupName+" not in codeTemplate");
		}
		if (!hasCodeActionArgs(groupName, actionArgs)) {
			StringBuffer args = new StringBuffer();
			for (String temp : actionArgs) {
				args.append(temp).append("\\|");
			}
			throw new CodeException("Group Action Args "+args.toString()+" not in codeTemplate");
		}
		return groupId;
	}

}
